package params

import (
	"encoding/json"
	"errors"
	"fmt"
	"micro-oauth/datamodels/enum"
	"strconv"
	"strings"
)



type Uint64StringSlice []uint64

func (slice Uint64StringSlice) MarshalJSON() ([]byte, error) {
	values := make([]string, len(slice))
	for i, value := range []uint64(slice) {
		values[i] = fmt.Sprintf(`"%v"`, value)
	}
	return []byte(fmt.Sprintf("[%v]", strings.Join(values, ","))), nil
}

func (slice *Uint64StringSlice) UnmarshalJSON(b []byte) error {
	// Try array of strings first.
	var values []string
	err := json.Unmarshal(b, &values)
	if err != nil {
		// Fall back to array of integers:
		var values []uint64
		if err := json.Unmarshal(b, &values); err != nil {
			return err
		}
		*slice = values
		return nil
	}
	*slice = make([]uint64, len(values))
	for i, value := range values {
		value, err := strconv.ParseUint(value, 10, 64)
		if err != nil {
			return err
		}
		(*slice)[i] = value
	}
	return nil
}

type ListRequest struct {
	Limit           uint64 `form:"limit"`
	Offset          uint64 `form:"offset"`
	SearchFields    []string
	SearchFieldsStr string `form:"search_fields"`
	SearchValue     string `form:"search_value"`
	PartnerId       uint64
	ScopeId         uint64
	OrderField      string            `form:"order_field"`
	OrderType       string            `form:"order_type"`
	Id              uint64            `form:"id" json:"id,string"`
	Ids             Uint64StringSlice `form:"ids"`
	Exclude         Exclude
}

func (r *ListRequest) CorrectSearchFields() {
	r.SearchFields = strings.Split(r.SearchFieldsStr, ",")
}

type Exclude struct {
	Id  uint64            `json:"id,string"`
	Ids Uint64StringSlice `json:"ids"`
}

type UserListRequest struct {
	ListRequest
	ScopeId      uint64            `form:"scope_id"`
	Types        []enum.UserType   `form:"types"`
	Statuses     []enum.UserStatus `form:"statuses"`
	BindStatus   []enum.BindStatus `form:"bind_status_list"`
	ThirdPartyId uint64            `form:"third_party_id" json:"third_party_id,string"`
	Name         string            `form:"name"`
	Code         string            `form:"code"`
	RoleId       uint64            `form:"role_id"`
	OrgId        uint64            `form:"org_id"`
	WithRoles    bool              `form:"with_roles"`
	WithScope    bool              `form:"with_scope"`
	Mail    	 string
}


type ResetPassWordReq struct {
	Type    int8  		 `form:"type" json:"type"` // 0:随机,1:手动
	IdList  []string	 `form:"id_list" json:"id_list"`	
	PassWd 	string	 	 `form:"pass_wd" json:"pass_wd"`
}

type DeviceListRequest struct {
	ListRequest
	Remark string            `form:"remark" json:"remark"`
	Status enum.DeviceStatus `form:"status" json:"status"`
	UUID   string            `form:"uuid" json:"uuid"`
}

type UserUpdateRequest struct {
	UpdateField []string
	PartnerId   uint64
	Id          uint64  `uri:"id"`
	IsLocked    *bool   `form:"is_locked" json:"is_locked"`
	IsSystem    *bool   `form:"is_system" json:"is_system"`
	Code        string  `form:"code" json:"code"`
	Name        string  `form:"name" json:"name"`
	UpdatePwd   bool    `form:"update_password" json:"update_password"`
	OldPwd      string  `form:"old_password" json:"old_password"`
	NewPwd      string  `form:"new_password" json:"new_password"`
	Remark      *string `form:"remark" json:"remark"`
	Mail 		string	`form:"mail" json:"mail"`
	LanType 	string 	`form:"lan_type" json:"lan_type"` // 0:中文,1:英文
	BindStatus  string	`form:"bind_status" json:"bind_status"`
}

type UserDisableRequest struct {
	Id          uint64
	Status      enum.UserStatus
}

type UserPassWdMailReq struct {
	UserId     uint64
	Host 	   string
	Mail 	   string   `form:"mail" json:"mail"`
}

type UserNewPassWdResetReq struct {
	UserId     uint64
	Code 	   string	`form:"code" json:"code"`
	PassWord   string	`form:"pass_word" json:"pass_word"`
	Mail 	   string	`form:"mail" json:"mail"`

}

type UserCreateRequest struct {
	IsLocked *bool  `json:"is_locked"`
	IsSystem *bool  `json:"is_system"`
	Code     string `json:"code"`
	Name     string `json:"name"`
	Pwd      string `json:"password"`
	Remark   string `json:"remark"`
	ScopeId  uint64 `form:"id" json:"id"`
	LanType  string `json:"lan_type"` // 0:中文,1:英文
}

type DeviceCreateRequest struct {
	ClientId string `json:"client_id" form:"client_id"`
	UUID     string `json:"uuid" form:"uuid"`
	Remark   string `json:"remark" form:"remark"`
	Status        enum.DeviceStatus `json:"status" form:"status"`  // 所有创建时的状态都应该是INIT
	Manufacturer  string `json:"manufacturer"`   // 设备制造商
	Brand         string `json:"brand"`          // 设备品牌
	Model         string `json:"model"`          // 设备型号
	SystemName    string `json:"system_name"`    // 系统名
	SystemVersion string `json:"system_version"` // 系统版本
}

type UserPassWdRuleReq struct {
	UserId 			uint64
	RuleId			string	`json:"rule_id"`
	PasswordForm 	struct{
		Number  	bool 	`json:"number"`
		Letter  	bool 	`json:"letter"`
		BigLetter	bool	`json:"big_letter"`
		SmallLetter bool	`json:"small_letter"`
		Symbol		bool	`json:"symbol"`
	} `json:"password_form"`
	PasswordLength  struct{
		Start int	`json:"start"`
		End   int	`json:"end"`
	} `json:"password_length"`
	LoginStatus		int		`json:"login_status"`
	//PasswordExp     int64	`json:"password_exp"`
	ExpireDay		int 	`json:"expire_day"`
	ExpireMonth		int 	`json:"expire_month"`
}





func (req *DeviceCreateRequest) Validate() error {
	req.UUID = strings.Trim(req.UUID, " \t\n")
	req.Remark = strings.Trim(req.Remark, " \t\n")
	if req.UUID == "" {
		return errors.New("uuid can't be empty")
	}
	req.ClientId = strings.Trim(req.ClientId, " \t\n")
	if req.ClientId == "" {
		return errors.New("no client_id")
	}
	return nil
}

type DeviceUpdateRequest struct {
	UUID          *string `json:"uuid" form:"uuid"`
	Remark        *string `json:"remark" form:"remark"`
	Status        *string `json:"status" form:"status"`
	Manufacturer  *string `json:"manufacturer" gorm:"size:50"`   // 设备制造商
	Brand         *string `json:"brand" gorm:"size:50"`          // 设备品牌
	Model         *string `json:"model" gorm:"size:50"`          // 设备型号
	SystemName    *string `json:"system_name" gorm:"size:50"`    // 系统名
	SystemVersion *string `json:"system_version" gorm:"size:50"` // 系统版本
}

func (req *DeviceUpdateRequest) Validate() error {
	if req.UUID == nil && req.Remark == nil && req.Status == nil {
		return errors.New("params is empty")
	}
	if req.UUID != nil {
		uuid := strings.Trim(*req.UUID, " \t\n")
		req.UUID = &uuid
	}
	if req.Remark != nil {
		remark := strings.Trim(*req.Remark, " \t\n")
		req.Remark = &remark
	}
	if req.Status != nil {
		status := strings.Trim(*req.Status, " \t\n")
		if enum.DeviceStatus(status) != enum.DeviceStatus_Active && enum.DeviceStatus(status) != enum.DeviceStatus_Forbidden {
			return errors.New("wrong device status(only can be Active or Forbidden")
		}
		req.Status = &status
	}
	if req.UUID != nil {
		uuid := strings.Trim(*req.UUID, " \t\n")
		if uuid == "" {
			return errors.New("uuid can't be empty")
		}
		req.UUID = &uuid
	}
	return nil
}

type PartnerListRequest struct {
	Name string `form:"name"`
	Code string `form:"code"`
	ListRequest
}

type PartnerUpdateRequest struct {
	Id          uint64 `form:"id" json:"id"`
	Name        string `form:"name" json:"name"`
	Code        string `form:"code" json:"code"`
	Description string `form:"description" json:"description"`
	Remark      string `form:"remark" json:"remark"`
}

type PartnerAddRequest struct {
	Name        string `form:"name" json:"name"`
	Code        string `form:"code" json:"code"`
	Description string `form:"description" json:"description"`
	Remark      string `form:"remark" json:"remark"`
}

func (req *PartnerAddRequest) Validate() error {
	req.Name = strings.Trim(req.Name, " \t\n")
	req.Code = strings.Trim(req.Code, " \t\n")
	if req.Name == "" || req.Code == "" {
		return errors.New("name or code can't be empty")
	}
	return nil
}

type RoleListRequest struct {
	ListRequest
	ScopeId           uint64            `form:"scope_id" json:"scope_id"`
	Name              string            `form:"name" json:"name"`
	Code              string            `form:"code" json:"code"`
	UserIds           Uint64StringSlice `form:"user_ids" json:"user_ids"`
	IncludePermission bool              `form:"include_permission" json:"include_permission"`
	LanType 		  	  string `form:"lan" json:"lan"`
}

type RoleCreateRequest struct {
	Code        string `form:"code" json:"code"`
	Name        string `form:"name" json:"name"`
	ScopeId     uint64 `form:"scope_id"`
	Description string `form:"description" json:"description"`
	LanType 	string `form:"lan" json:"lan"`
}

func (req *RoleCreateRequest) Validate() error {
	req.Name = strings.Trim(req.Name, " \t\n")
	req.Code = strings.Trim(req.Code, " \t\n")
	if req.Name == "" || req.Code == "" {
		return errors.New("name or code can't be empty")
	}
	return nil
}

type RoleUpdateRequest struct {
	PartnerId uint64
	Id        uint64 `form:"id"`
	Name      string `form:"name" json:"name"`
	Code      string `form:"code" json:"code"`
	LanType   string `form:"lan" json:"lan"`
}

func (req *RoleUpdateRequest) Validate() error {
	req.Name = strings.Trim(req.Name, " \t\n")
	req.Code = strings.Trim(req.Code, " \t\n")
	if req.Id == 0 {
		return errors.New("id can't be null")
	}
	if len(req.Name) == 0 || len(req.Code) == 0 {
		return errors.New("role code or name cant not be empty")
	}
	return nil
}

type PermissionCreateRequest struct {
	PartnerId   uint64 `form:"partner_id" json:"partner_id,string"`
	ParentId    uint64 `form:"parent_id" json:"parent_id,string"`
	Name        string `form:"name" json:"name"`
	Code        string `form:"code" json:"code"`
	Description string `form:"description" json:"description"`
	Remark      string `form:"remark" json:"remark"`
	LanType 	string  `form:"lan" json:"lan"`
}

func (req *PermissionCreateRequest) Validate() error {
	req.Name = strings.Trim(req.Name, " \t\n")
	req.Code = strings.Trim(req.Code, " \t\n")
	req.Description = strings.Trim(req.Name, " \t\n")
	req.Remark = strings.Trim(req.Code, " \t\n")
	if len(req.Name) == 0 || len(req.Code) == 0 {
		return errors.New("name or code can't be empty")
	}
	if req.PartnerId == 0 {
		return errors.New("partner_id can not be empty")
	}
	return nil
}

type PermissionListRequest struct {
	ListRequest
	Name      string            `form:"name" json:"name"`
	Code      string            `form:"code" json:"code"`
	PartnerId uint64            `form:"partner_id" json:"partner_id"`
	RoleIds   Uint64StringSlice `form:"role_ids" json:"role_ids"`
	LanType   string			`form:"lan" json:"lan"`
	ParentIdList Uint64StringSlice
}

type PermissionUpdateRequest struct {
	Id          uint64 `form:"id" json:"id,string"`
	ParentId    uint64 `form:"parent_id" json:"parent_id,string"`
	Description string `form:"description" json:"description"`
	Remark      string `form:"remark" json:"remark"`
	Name        string `form:"name" json:"name"`
	Code        string `form:"code" json:"code"`
	LanType 	string `form:"lan" json:"lan"`
}

type PermissionAddAPIsRequest struct {
	APIIds Uint64StringSlice `form:"api_ids" json:"api_ids"`
	Id     uint64            `form:"id" json:"id,string"`
}

type PermissionMethodRequest struct {
	ServiceName string
	MethodList []*PermissionMethodItem
}

type PermissionMethodItem struct {
	MethodName string
	MethodType string
	Url string
}

type APIListRequest struct {
	ListRequest
	PartnerId     uint64            `form:"partner_id" json:"partner_id"`
	Name          string            `form:"name" json:"name"`
	Code          string            `form:"code" json:"code"`
	PermissionIds Uint64StringSlice `form:"permission_ids" json:"permission_ids"`
}

type UserAddRoleRequest struct {
	RoleIds Uint64StringSlice `form:"role_ids" json:"role_ids"`
	Id      uint64            `form:"id" json:"id,string"`
}

type APICreateRequest struct {
	Name        string          `json:"name" form:"name"`
	Code        string          `json:"code" form:"code"`
	URL         string          `json:"url" form:"url"`
	PartnerId   uint64          `json:"partner_id" form:"partner_id"`
	Method      enum.MethodType `json:"method" form:"method"`
	Description string          `json:"description" form:"description"`
	Remark      string          `json:"remark" form:"remark"`
}

func (req *APICreateRequest) Validate() error {
	req.Name = strings.Trim(req.Name, " \t\n")
	req.Code = strings.Trim(req.Code, " \t\n")
	req.Description = strings.Trim(req.Name, " \t\n")
	req.Remark = strings.Trim(req.Code, " \t\n")
	if len(req.Name) == 0 || len(req.Code) == 0 {
		return errors.New("name or code can't be empty")
	}
	methods := []enum.MethodType{enum.POST, enum.PUT, enum.GET, enum.DELETE}
	ok := false
	for _, m := range methods {
		if req.Method == m {
			ok = true
		}
	}
	if !ok {
		return errors.New("method invalid")
	}
	if req.PartnerId == 0 {
		return errors.New("partner can not be 0")
	}
	return nil
}

type APIUpdateRequest struct {
	Id          uint64          `json:"id,string" form:"id"`
	Name        string          `json:"name" form:"name"`
	Code        string          `json:"code" form:"code"`
	URL         string          `json:"url" form:"url"`
	Method      enum.MethodType `json:"method" form:"method"`
	Description string          `json:"description" form:"description"`
	Remark      string          `json:"remark" form:"remark"`
}

func (req *APIUpdateRequest) Validate() error {
	req.Name = strings.Trim(req.Name, " \t\n")
	req.Code = strings.Trim(req.Code, " \t\n")
	req.Description = strings.Trim(req.Description, " \t\n")
	req.Remark = strings.Trim(req.Remark, " \t\n")
	if len(req.Name) == 0 || len(req.Code) == 0 {
		return errors.New("name or code can't be empty")
	}
	methods := []enum.MethodType{enum.POST, enum.PUT, enum.GET, enum.DELETE}
	ok := false
	for _, m := range methods {
		if req.Method == m {
			ok = true
		}
	}
	if !ok {
		return errors.New("method invalid")
	}
	return nil
}

type AuthenticateRequest struct {
	Token           string
	APICode         string
	CheckPermission bool
}

type AuthenticateResponse struct {
	PartnerId  uint64 `json:"partner_id"`
	UserId     uint64 `json:"user_id"`
	ScopeId    uint64 `json:"scope_id"`
	TerminalId uint64 `json:"terminal_id,omitempty"`
}
